<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <div id="content" class="wrapper" title="hello attributes">
        Hello attributes
      </div>
      <ul id="myList"> 
        <li>Item 1</li> 
        <li>Item 2</li> 
        <li>Item 3</li> 
       </ul>
      <ul id="myList1"><li>Item 11</li><li>Item 21</li><li>Item 31</li></ul>
    </div>
  </body>
  <script>
    /** 6.attributes 属性（粗略简记，不常用）
     *    a.Element 类型是唯一使用 attributes 属性的 DOM 节点类型。
     *    b.attributes 属性包含一个NamedNodeMap 实例，是一个类似 NodeList 的“实时”集合。
     *    c.元素的每个属性都表示为一个 Attr 节点，并保存在这个 NamedNodeMap 对象中。
     *    d.NamedNodeMap 对象包含下列方法：
     *      + getNamedItem(name)，返回 nodeName 属性等于 name 的节点；
     *      + removeNamedItem(name)，删除 nodeName 属性等于 name 的节点；
     *      + setNamedItem(node)，向列表中添加 node 节点，以其 nodeName 为索引；
     *      + item(pos)，返回索引位置 pos 处的节点。
     *    e.attributes 属性中的每个节点的 nodeName 是对应属性的名字，nodeValue 是属性的值。
     *    f.removeNamedItem()方法与元素上的 removeAttribute()方法类似，也是删除指定名字的属性。不同之处，就是removeNamedItem()返回表示被删除属性的Attr
     *      节点。
     *    g.setNamedItem()方法很少使用，它接收一个属性节点，然后给元素添加一个新属性。
     *    h.一般来说，因为使用起来更简便，通常开发者更喜欢使用 getAttribute()、removeAttribute()和 setAttribute()方法，而不是刚刚介绍的 NamedNodeMap
     *      对象的方法。
     *    i.attributes 属性最有用的场景是需要迭代元素上所有属性的时候。这时候往往是要把 DOM 结构序列化为 XML 或 HTML 字符串。
     * **/
    function checkedAttribute() {
      let dom = document.getElementById("content");
      //1.获取属性值
      let attributeValue1 = dom.attributes.getNamedItem("class").nodeValue;
      let attributeValue2 = dom.attributes["title"].nodeValue;
      console.log(attributeValue1, attributeValue2); //wrapper hello attributes
      //2.设置属性值
      dom.attributes["title"].nodeValue = "HELLO ATTR";
      console.log(dom.attributes["title"].nodeValue); //HELLO ATTR
      let attr = document.createAttribute("data-index"); //创建属性节点
      dom.attributes.setNamedItem(attr);
      dom.attributes["data-index"].nodeValue = "HELLO DATA-INDEX";
      //3.删除节点
      let titleAttr = dom.attributes.removeNamedItem("title");
      console.log(titleAttr); //title='HELLO ATTR';
    }
    //checkedAttribute();
    //获取一个dom元素上所有的属性节点
    function outputAttributes(element) {
      let pairs = [];
      for (let i = 0, len = element.attributes.length; i < len; ++i) {
        const attribute = element.attributes[i];
        pairs.push(`${attribute.nodeName}="${attribute.nodeValue}"`);
      }
      return pairs.join(" ");
    }
    //这个函数使用数组存储每个名/值对，迭代完所有属性后，再将这些名/值对用空格拼接在一起。（这个技术常用于序列化为长字符串。）

    /** 7.创建元素
     *    a.可以使用 document.createElement()方法创建新元素。这个方法接收一个参数，即要创建元素的标签名。
     *    b.HTML 文档中，标签名是不区分大小写的，而 XML 文档（包括 XHTML）是区分大小写的。
     *    c.使用 createElement()方法创建新元素的同时也会将其 ownerDocument 属性设置为 document。此时，可以再为其添加属性、添加更多子元素。
     *    d.在新元素上设置这些属性只会附加信息。因为这个元素还没有添加到文档树，所以不会影响浏览器显示。
     *    e.元素被添加到文档树之后，浏览器会立即将其渲染出来。之后再对这个元素所做的任何修改，都会立即在浏览器中反映出来。
     *      document.body.appendChild(div);
     * **/

     /** 8.元素后代
      *    a.元素可以拥有任意多个子元素和后代元素，因为元素本身也可以是其他元素的子元素。
      *    b.childNodes属性包含元素所有的子节点，这些子节点可能是其他元素、文本节点、注释或处理指令。不同浏览器在识别这些节点时的表现有明显不同。
      *    c.要取得某个元素的子节点和其他后代节点，可以使用元素的 getElementsByTagName()方法。在元素上调用这个方法与在文档上调用是一样的，只不过搜索范围限
      *      制在当前元素之内，即只会返回当前元素的后代。
      * 
      * **/
     function checkedDescendantElement(){
       let dom = document.getElementById('myList');
       let dom1 = document.getElementById('myList1');
       console.log(dom.childNodes);//NodeList(7) [text, li, text, li, text, li, text]
       console.log(dom1.childNodes);//NodeList(3) [li, li, li]
       //方法一
       for (let i = 0, len = dom.childNodes.length; i < len; ++i) { 
        if (dom.childNodes[i].nodeType == 1) { //如果为元素节点
        // 执行某个操作
        } 
        }
        //方法二
       let dom3 = document.getElementById("myList"); 
       let dom4 = dom3.getElementsByTagName("li");
       console.log(dom4);//HTMLCollection(3) [li, li, li]
     }
     checkedDescendantElement();
  </script>
</html>
